package system

import (
	"context"
	"encoding/json"
	"fmt"
	mqtt "github.com/eclipse/paho.mqtt.golang"
	"github.com/flipped-aurora/gin-vue-admin/server/global"
	"github.com/flipped-aurora/gin-vue-admin/server/model/system"
	systemReq "github.com/flipped-aurora/gin-vue-admin/server/model/system/request"
	"go.uber.org/zap"
	"gorm.io/gorm"
	"log"
	"strings"
)

type DeviceService struct {
}

// CreateDevice 创建设备表记录
// Author [yourname](https://github.com/yourname)
func (deviceService *DeviceService) CreateDevice(ctx context.Context, device *system.Device) (err error) {
	err = global.GVA_DB.Create(device).Error
	return err
}

// DeleteDevice 删除设备表记录
// Author [yourname](https://github.com/yourname)
func (deviceService *DeviceService) DeleteDevice(ctx context.Context, ID string) (err error) {
	err = global.GVA_DB.Delete(&system.Device{}, "id = ?", ID).Error
	return err
}

// DeleteDeviceByIds 批量删除设备表记录
// Author [yourname](https://github.com/yourname)
func (deviceService *DeviceService) DeleteDeviceByIds(ctx context.Context, IDs []string) (err error) {
	err = global.GVA_DB.Delete(&[]system.Device{}, "id in ?", IDs).Error
	return err
}

// UpdateDevice 更新设备表记录
// Author [yourname](https://github.com/yourname)
func (deviceService *DeviceService) UpdateDevice(ctx context.Context, device system.Device) (err error) {
	err = global.GVA_DB.Model(&system.Device{}).Where("id = ?", device.ID).Updates(&device).Error
	return err
}

// GetDevice 根据ID获取设备表记录
// Author [yourname](https://github.com/yourname)
func (deviceService *DeviceService) GetDevice(ctx context.Context, ID string) (device system.Device, err error) {
	err = global.GVA_DB.Where("id = ?", ID).First(&device).Error
	return
}

// GetDeviceInfoList 分页获取设备表记录
// Author [yourname](https://github.com/yourname)
func (deviceService *DeviceService) GetDeviceInfoList(ctx context.Context, info systemReq.DeviceSearch) (list []system.Device, total int64, err error) {
	limit := info.PageSize
	offset := info.PageSize * (info.Page - 1)
	// 创建db
	db := global.GVA_DB.Model(&system.Device{})
	var devices []system.Device
	// 如果有条件搜索 下方会自动创建搜索语句
	if len(info.CreatedAtRange) == 2 {
		db = db.Where("created_at BETWEEN ? AND ?", info.CreatedAtRange[0], info.CreatedAtRange[1])
	}

	err = db.Count(&total).Error
	if err != nil {
		return
	}

	if limit != 0 {
		db = db.Limit(limit).Offset(offset)
	}

	err = db.Find(&devices).Error
	return devices, total, err
}
func (deviceService *DeviceService) GetDevicePublic(ctx context.Context) {
	// 此方法为获取数据源定义的数据
	// 请自行实现
}

// 设备状态常量（与前端统一）
const (
	DeviceStatusRunning = "1"
	DeviceStatusStopped = "2"
	DeviceStatusError   = "3"
)

// 合法状态集合（更新为数字）
var ValidDeviceStatus = map[string]bool{
	DeviceStatusRunning: true,
	DeviceStatusStopped: true,
	DeviceStatusError:   true,
}

// 填充funcName
// Author [yourname](https://github.com/yourname)
func (deviceService *DeviceService) SearchDevice(ctx context.Context, deviceSearch systemReq.DeviceSearch) ([]system.Device, int64, error) {
	// 1. 状态参数校验（防止非法状态查询）
	if deviceSearch.Device_status != "" {
		if !ValidDeviceStatus[deviceSearch.Device_status] {
			return nil, 0, fmt.Errorf("非法设备状态: %s", deviceSearch.Device_status)
		}
	}

	// 2. 构建查询
	db := global.GVA_DB.Model(&system.Device{})

	// 3. 条件拼接（复用原逻辑，可优化为结构体标签自动拼接）
	if deviceSearch.Device_sn != "" {
		db = db.Where("device_sn = ?", deviceSearch.Device_sn)
	}
	if deviceSearch.Device_name != "" {
		db = db.Where("device_name = ?", deviceSearch.Device_name)
	}
	if deviceSearch.Device_type != "" {
		db = db.Where("device_type = ?", deviceSearch.Device_type)
	}
	if deviceSearch.Device_address != "" {
		db = db.Where("device_address = ?", deviceSearch.Device_address)
	}
	if deviceSearch.Device_after_sales != "" {
		db = db.Where("device_after_sales = ?", deviceSearch.Device_after_sales)
	}
	if deviceSearch.Device_version != "" {
		db = db.Where("device_version = ?", deviceSearch.Device_version)
	}
	if deviceSearch.Device_status != "" {
		db = db.Where("device_status = ?", deviceSearch.Device_status)
	}

	// 4. 统计总数
	var total int64
	if err := db.Count(&total).Error; err != nil {
		return nil, 0, err
	}

	// 5. 分页处理（增加边界值保护）
	if deviceSearch.Page <= 0 {
		deviceSearch.Page = 1
	}
	if deviceSearch.PageSize <= 0 || deviceSearch.PageSize > 100 { // 限制最大页大小
		deviceSearch.PageSize = 10
	}
	db = db.Offset((deviceSearch.Page - 1) * deviceSearch.PageSize).Limit(deviceSearch.PageSize)

	// 6. 执行查询
	var devices []system.Device
	if err := db.Find(&devices).Error; err != nil {
		return nil, 0, err
	}

	return devices, total, nil
}

// Running 运行监测
// Author [yourname](https://github.com/yourname)
func (deviceService *DeviceService) Running(ctx context.Context) (map[string]int64, error) {
	var counts struct {
		Total         int64
		Running       int64 // 进行中(1)
		Stopped       int64 // 已停止(2)
		Abnormal      int64 // 设备异常(3)
		SmartTerminal int64 // 智能终端(4)
		EdgeGateway   int64 // 边缘网关(5)
	}

	err := global.GVA_DB.Model(&system.Device{}).
		Select(
			"COUNT(*) as total",
			"SUM(CASE WHEN device_status = 1 THEN 1 ELSE 0 END) as running",
			"SUM(CASE WHEN device_status = 2 THEN 1 ELSE 0 END) as stopped",
			"SUM(CASE WHEN device_status = 3 THEN 1 ELSE 0 END) as abnormal",
			"SUM(CASE WHEN device_type = 1 THEN 1 ELSE 0 END) as smart_terminal",
			"SUM(CASE WHEN device_type = 2 THEN 1 ELSE 0 END) as edge_gateway",
		).
		Scan(&counts).Error

	if err != nil {
		return nil, err
	}

	return map[string]int64{
		"total":         counts.Total,
		"running":       counts.Running,
		"stopped":       counts.Stopped,
		"abnormal":      counts.Abnormal,
		"smartTerminal": counts.SmartTerminal,
		"edgeGateway":   counts.EdgeGateway,
	}, nil
}

type DeviceServicess struct {
	DB         *gorm.DB
	MQTTClient mqtt.Client
}

// NewDeviceService 创建新的设备服务
func NewDeviceService(db *gorm.DB, mqttClient mqtt.Client) *DeviceServicess {
	return &DeviceServicess{
		DB:         db,
		MQTTClient: mqttClient,
	}
}

// HandleMQTTDeviceStatus 处理MQTT设备状态消息
func (ds *DeviceServicess) HandleMQTTDeviceStatus(topic string, payload []byte) error {
	global.GVA_LOG.Info("处理MQTT消息", zap.String("topic", topic), zap.String("payload", string(payload)))

	// 定义MQTT消息结构体
	var msg struct {
		DeviceSN           string `json:"device_sn"`
		DeviceName         string `json:"device_name"`
		DeviceStatus       string `json:"device_status"`
		DeviceStatusReason string `json:"device_status_reason"`
		DeviceAfterSales   string `json:"device_after_sales"`
	}

	// 解析JSON消息
	if err := json.Unmarshal(payload, &msg); err != nil {
		global.GVA_LOG.Error("解析MQTT消息失败", zap.Error(err))
		return err
	}

	// 验证设备编号
	if msg.DeviceSN == "" {
		return fmt.Errorf("设备编号为空")
	}

	// 查询设备是否存在
	var device system.Device
	err := ds.DB.Where("device_sn = ?", msg.DeviceSN).First(&device).Error
	
	if err == gorm.ErrRecordNotFound {
		// 设备不存在，创建新设备
		device = system.Device{
			Device_sn:            &msg.DeviceSN,
			Device_name:          &msg.DeviceName,
			Device_status:        &msg.DeviceStatus,
			Device_status_reason: &msg.DeviceStatusReason,
			Device_after_sales:   &msg.DeviceAfterSales,
		}
		
		// 设置默认值
		if *device.Device_name == "" {
			defaultName := "未知设备"
			device.Device_name = &defaultName
		}
		if *device.Device_status == "" {
			defaultStatus := "1"
			device.Device_status = &defaultStatus
		}
		
		err = ds.DB.Create(&device).Error
		if err != nil {
			global.GVA_LOG.Error("创建设备失败", zap.Error(err))
			return err
		}
		global.GVA_LOG.Info("设备创建成功", zap.String("device_sn", msg.DeviceSN))
	} else if err != nil {
		global.GVA_LOG.Error("查询设备失败", zap.Error(err))
		return err
	} else {
		// 设备存在，更新状态
		updates := make(map[string]interface{})
		
		if msg.DeviceStatus != "" {
			updates["device_status"] = msg.DeviceStatus
		}
		if msg.DeviceStatusReason != "" {
			updates["device_status_reason"] = msg.DeviceStatusReason
		}
		if msg.DeviceAfterSales != "" {
			updates["device_after_sales"] = msg.DeviceAfterSales
		}
		if msg.DeviceName != "" {
			updates["device_name"] = msg.DeviceName
		}
		
		if len(updates) > 0 {
			err = ds.DB.Model(&device).Updates(updates).Error
			if err != nil {
				global.GVA_LOG.Error("更新设备失败", zap.Error(err))
				return err
			}
			global.GVA_LOG.Info("设备更新成功", zap.String("device_sn", msg.DeviceSN))
		}
	}

	return nil
}

// 定义 MQTT 消息结构体（与设备状态字段对齐）
type MqttDevicePayload struct {
	DeviceSn           string `json:"device_sn"`            // 设备编号
	DeviceName         string `json:"device_name"`          // 设备名称
	DeviceStatus       string `json:"device_status"`        // 设备状态
	DeviceStatusReason string `json:"device_status_reason"` // 状态原因
	DeviceAfterSales   string `json:"device_after_sales"`   // 售后负责人
}

// 启动 MQTT 订阅，接收设备状态变更并更新数据库
func (deviceService *DeviceService) StartMQTTSubscription(ctx context.Context, mqttClient mqtt.Client, topic string) error {
	// MQTT 消息处理函数
	messageHandler := func(client mqtt.Client, msg mqtt.Message) {
		var payload MqttDevicePayload
		if err := json.Unmarshal(msg.Payload(), &payload); err != nil {
			log.Printf("MQTT 消息解析失败: %v,  payload: %s", err, msg.Payload())
			return
		}

		// 根据 device_sn 更新数据库（假设 device_sn 是唯一标识）
		var device system.Device
		err := global.GVA_DB.Where("device_sn = ?", payload.DeviceSn).First(&device).Error
		if err != nil {
			if err == gorm.ErrRecordNotFound {
				// 设备不存在则创建（根据需求决定是否需要）
				device = system.Device{
					Device_sn:            &payload.DeviceSn,
					Device_name:          &payload.DeviceName,
					Device_status:        &payload.DeviceStatus,
					Device_status_reason: &payload.DeviceStatusReason,
					Device_after_sales:   &payload.DeviceAfterSales,
				}
				err = global.GVA_DB.Create(&device).Error
			}
			if err != nil {
				log.Printf("更新/创建设备失败: %v, payload: %+v", err, payload)
				return
			}
		} else {
			// 设备存在则更新状态字段
			err = global.GVA_DB.Model(&device).Updates(map[string]interface{}{
				"device_status":        payload.DeviceStatus,
				"device_status_reason": payload.DeviceStatusReason,
				"device_after_sales":   payload.DeviceAfterSales,
			}).Error
			if err != nil {
				log.Printf("更新设备状态失败: %v, payload: %+v", err, payload)
				return
			}
		}

		log.Printf("MQTT 消息处理完成，设备 %s 状态已更新", payload.DeviceSn)
	}

	// 订阅 MQTT 主题
	token := mqttClient.Subscribe(topic, 0, messageHandler)
	if token.Wait() && token.Error() != nil {
		return fmt.Errorf("MQTT 订阅失败: %v", token.Error())
	}

	log.Printf("已订阅 MQTT 主题: %s", topic)
	return nil
}
func (deviceService *DeviceService) Realtime(ctx context.Context) (interface{}, error) {
	type DeviceResp struct {
		DeviceName         string `json:"deviceName" gorm:"column:device_name"`
		Status             string `json:"status" gorm:"column:device_status"`
		DeviceStatusReason string `json:"deviceStatusReason" gorm:"column:device_status_reason"`
		DeviceAfterSales   string `json:"deviceAfterSales" gorm:"column:device_after_sales"`
	}

	var devices []DeviceResp
	err := global.GVA_DB.Model(&system.Device{}).
		Select("device_name, device_status, device_status_reason, device_after_sales").
		Scan(&devices).Error
	if err != nil {
		return nil, fmt.Errorf("数据库查询失败: %+v", err)
	}

	// 状态转换（保持原有逻辑）
	statusMap := map[string]string{"1": "进行中", "2": "已停止", "3": "设备异常"}
	for i := range devices {
		if statusText, ok := statusMap[devices[i].Status]; ok {
			devices[i].Status = statusText
		}
	}

	return devices, nil
}

// DeviceService 设备服务
// DeviceResp 设备响应结构
// 定义用于接收统计结果的结构体
// 设备地址统计信息（包含设备列表）
type DeviceAddressStat struct {
	DeviceAddress string       `json:"device_address"` // 省份
	DeviceStatus  string       `json:"device_status"`  // 设备状态
	DeviceCount   int64        `json:"device_count"`   // 设备数量
	Devices       []DeviceInfo `json:"devices"`        // 设备列表
}

// 设备信息
type DeviceInfo struct {
	DeviceName   string `json:"device_name"`   // 设备名称
	DeviceStatus string `json:"device_status"` // 设备状态
	Location     string `json:"location"`      // 位置信息
}

// 映射设备状态
func mapStatus(status string) string {
	switch status {
	case "1":
		return "进行中"
	case "2":
		return "已停止"
	case "3":
		return "异常"
	default:
		return "未知"
	}
}

// Address 查询设备地址和状态分布
func (deviceService *DeviceService) Address(ctx context.Context) (result []DeviceAddressStat, err error) {
	// 第一步：查询省份和状态统计
	var stats []struct {
		DeviceAddress string `json:"device_address"`
		DeviceStatus  string `json:"device_status"`
		DeviceCount   int64  `json:"device_count"`
	}
	const sqlSelect = `
        CASE 
            WHEN device_address LIKE '北京市%' THEN '北京市'
            WHEN device_address LIKE '天津市%' THEN '天津市'
            WHEN device_address LIKE '上海市%' THEN '上海市'
            WHEN device_address LIKE '重庆市%' THEN '重庆市'
            WHEN device_address LIKE '河北省%' THEN '河北省'
            WHEN device_address LIKE '山西省%' THEN '山西省'
            WHEN device_address LIKE '辽宁省%' THEN '辽宁省'
            WHEN device_address LIKE '吉林省%' THEN '吉林省'
            WHEN device_address LIKE '黑龙江省%' THEN '黑龙江省'
            WHEN device_address LIKE '江苏省%' THEN '江苏省'
            WHEN device_address LIKE '浙江省%' THEN '浙江省'
            WHEN device_address LIKE '安徽省%' THEN '安徽省'
            WHEN device_address LIKE '福建省%' THEN '福建省'
            WHEN device_address LIKE '江西省%' THEN '江西省'
            WHEN device_address LIKE '山东省%' THEN '山东省'
            WHEN device_address LIKE '河南省%' THEN '河南省'
            WHEN device_address LIKE '湖北省%' THEN '湖北省'
            WHEN device_address LIKE '湖南省%' THEN '湖南省'
            WHEN device_address LIKE '广东省%' THEN '广东省'
            WHEN device_address LIKE '海南省%' THEN '海南省'
            WHEN device_address LIKE '四川省%' THEN '四川省'
            WHEN device_address LIKE '贵州省%' THEN '贵州省'
            WHEN device_address LIKE '云南省%' THEN '云南省'
            WHEN device_address LIKE '陕西省%' THEN '陕西省'
            WHEN device_address LIKE '甘肃省%' THEN '甘肃省'
            WHEN device_address LIKE '青海省%' THEN '青海省'
            WHEN device_address LIKE '台湾省%' THEN '台湾省'
            WHEN device_address LIKE '内蒙古自治区%' THEN '内蒙古自治区'
            WHEN device_address LIKE '广西壮族自治区%' THEN '广西壮族自治区'
            WHEN device_address LIKE '西藏自治区%' THEN '西藏自治区'
            WHEN device_address LIKE '宁夏回族自治区%' THEN '宁夏回族自治区'
            WHEN device_address LIKE '新疆维吾尔自治区%' THEN '新疆维吾尔自治区'
            ELSE '其他'
        END AS device_address,
        CASE device_status 
            WHEN '1' THEN '进行中' 
            WHEN '2' THEN '已停止' 
            WHEN '3' THEN '异常' 
            ELSE '未知' 
        END AS device_status,
        COUNT(*) AS device_count
    `
	err = global.GVA_DB.Model(&system.Device{}).
		Select(sqlSelect).
		Group("device_address, device_status").
		Scan(&stats).Error

	if err != nil {
		global.GVA_LOG.Error("查询设备地址统计数据失败", zap.Error(err))
		return []DeviceAddressStat{}, err
	}
	// 第二步：为每个统计项查询设备列表
	result = make([]DeviceAddressStat, len(stats))
	for i, stat := range stats {
		var devices []DeviceInfo

		// 构建查询条件
		addressCondition := fmt.Sprintf("device_address LIKE '%s%%'", strings.TrimRight(stat.DeviceAddress, "省市区自治区"))
		if stat.DeviceAddress == "其他" {
			addressCondition = "device_address NOT LIKE '北京市%' AND ..." // 所有其他条件
		}

		statusCondition := ""
		switch stat.DeviceStatus {
		case "进行中":
			statusCondition = "device_status = '1'"
		case "已停止":
			statusCondition = "device_status = '2'"
		case "异常":
			statusCondition = "device_status = '3'"
		default:
			statusCondition = "device_status NOT IN ('1', '2', '3')"
		}

		// 查询设备列表（限制返回数量）
		err := global.GVA_DB.Model(&system.Device{}).
			Where(addressCondition).
			Where(statusCondition).
			Limit(10). // 限制每个分组最多返回10个设备，避免数据量过大
			Select("device_name, device_status, device_address AS location").
			Scan(&devices).Error

		if err != nil {
			global.GVA_LOG.Warn("查询设备列表失败", zap.Error(err))
			// 继续处理其他分组，不中断整个请求
		}

		// 转换设备状态
		for j := range devices {
			devices[j].DeviceStatus = mapStatus(devices[j].DeviceStatus)
		}

		result[i] = DeviceAddressStat{
			DeviceAddress: stat.DeviceAddress,
			DeviceStatus:  stat.DeviceStatus,
			DeviceCount:   stat.DeviceCount,
			Devices:       devices,
		}
	}

	return
}

